/**
 * @file epd_ssd167x.c
 */
#include "epd_ssd167x.h"
#include <math.h>

/* Reuse existing driver headers */
#if EPD_ENABLE
#include "EPD_7in5bc.h"
#endif

static inline uint32_t plane_size_bytes(uint16_t w, uint16_t h)
{
    return ((uint32_t)w * (uint32_t)h) / 8U;
}

#if EPD_ENABLE
epd_err_t epd_ssd167x_init(epd_ssd167x_t *dev)
{
    if (dev == NULL) { return EPD_ERR_PARAM; }
    /* The underlying EPD_7IN5BC_Init sets resolution to 640x384 in the provided driver */
    EPD_7IN5BC_Init();
    dev->width = EPD_7IN5BC_WIDTH;
    dev->height = EPD_7IN5BC_HEIGHT;
    return EPD_OK;
}

epd_err_t epd_ssd167x_clear(epd_ssd167x_t *dev)
{
    if (dev == NULL) { return EPD_ERR_PARAM; }
    EPD_7IN5BC_Clear();
    return EPD_OK;
}

epd_err_t epd_ssd167x_display(epd_ssd167x_t *dev, const uint8_t *bw, const uint8_t *ry)
{
    if ((dev == NULL) || (bw == NULL) || (ry == NULL)) { return EPD_ERR_PARAM; }
    const uint32_t need = plane_size_bytes(dev->width, dev->height);
    (void)need; /* For MISRA: size checks can be done by caller; using raw pointer here. */
    EPD_7IN5BC_Display(bw, ry);
    return EPD_OK;
}

epd_err_t epd_ssd167x_sleep(epd_ssd167x_t *dev, bool deep)
{
    (void)dev;
    /* 厂商驱动不区分轻/深休眠；统一调用 Sleep 以确保上电序列正确结束 */
    (void)deep;
    EPD_7IN5BC_Sleep();
    return EPD_OK;
}

epd_err_t epd_ssd167x_set_refresh_rate(epd_ssd167x_t *dev, double hz)
{
    if (dev == NULL) { return EPD_ERR_PARAM; }
    if ((hz < 1.0) || (hz > 30.0)) { return EPD_ERR_PARAM; }
    /* Step granularity enforcement to 0.1Hz */
    const double step = 0.1;
    const double steps = floor((hz + (step/2.0)) / step);
    dev->refresh_rate_hz = steps * step;
    return EPD_OK;
}
#else
#include "epd_ssd167x.h"

epd_err_t epd_ssd167x_init(epd_ssd167x_t *dev)
{
    (void)dev; return EPD_ERR_UNSUPPORTED;
}

epd_err_t epd_ssd167x_clear(epd_ssd167x_t *dev)
{
    (void)dev; return EPD_ERR_UNSUPPORTED;
}

epd_err_t epd_ssd167x_display(epd_ssd167x_t *dev, const uint8_t *bw, const uint8_t *ry)
{
    (void)dev; (void)bw; (void)ry; return EPD_ERR_UNSUPPORTED;
}

epd_err_t epd_ssd167x_sleep(epd_ssd167x_t *dev, bool deep)
{
    (void)dev; (void)deep; return EPD_ERR_UNSUPPORTED;
}

epd_err_t epd_ssd167x_set_refresh_rate(epd_ssd167x_t *dev, double hz)
{
    (void)dev; (void)hz; return EPD_ERR_UNSUPPORTED;
}
#endif